/************************************************************************************
 *                                .                                                 *
 *                                .                                                 *
 ************************************************************************************/
package jMiiEditor.mii.introspection;

import jMiiEditor.mii.MIIGETTER;
import jMiiEditor.mii.Mii;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Map;
import junit.framework.TestCase;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import cx.ath.choisnet.lang.introspection.IntrospectionException;
import cx.ath.choisnet.lang.introspection.IntrospectionInvokeException;
import cx.ath.choisnet.lang.introspection.method.IntrospectionCompareException;
import utils.BinStuffs;

/**
 * @author CC
 *
 */
public class MiiGetterIntrospectionTest extends TestCase
{
    /** Some logs */
    private static Logger slogger = Logger.getLogger(MiiGetterIntrospectionTest.class);

    private MiiGetterIntrospection testMiiGetterInspection;
    private String ressource = "/jMiiEditor/mii/Mii.mii";
    private Mii mii;

    public void setUp() throws IOException
    {
        slogger.setLevel( Level.ALL );

        slogger.info( "setUp()--> Build MiiGetterInspectionOLD object -------------");
        testMiiGetterInspection = new MiiGetterIntrospection();

        slogger.info( "setUp() --> Load a Mii -------------------------------------");
        InputStream is = getClass().getResourceAsStream(ressource);

        slogger.info( "setUp() --> Load Mii : " + ressource );
        mii = new Mii( is );

        is.close();

        slogger.info( "setUp()-- done ---------------------------------------------");
    }

    public void testMiiGetterInspection()
    {
        slogger.info( "-- MiiGetterInspection()" );
        MiiGetterIntrospection instance = new MiiGetterIntrospection();

        assertNotNull( instance );
        slogger.info( "--" );
    }

    public void testCompareWithException() throws IntrospectionInvokeException
    {
        slogger.info( "---------- Check CompareWithException() -----------------");
        Mii mii2 = new Mii();

        int res = runCompareWithException( mii, mii2 );

        assertTrue( "Compare with an new empty Mii", res != 0 );

        Mii mii3 = new Mii( mii ); // use mii.clone()

        res = runCompareWithException( mii, mii3 );

        assertTrue( "Compare with an cloned Mii", res == 0 );
        slogger.info( "---------------------------------------------------------");
    }

    public void testCheckGetters() throws IntrospectionException
        // TODO add some assertions
    {
        slogger.info( "---------- Check getters --------------------------------");
        Map<String,MiiGetterIntrospectionItem> mg = testMiiGetterInspection.getMap();

        for( Map.Entry<String, MiiGetterIntrospectionItem> entry : mg.entrySet() ) {
            MiiGetterIntrospectionItem mi      = entry.getValue();
            MIIGETTER.Type          type    = mi.getType();

            if( type == MIIGETTER.Type.BOOL ) {
                slogger.info( entry.getKey() + " = " + mi.getBooleanValue( mii ) );
            }
            else if( type == MIIGETTER.Type.BYTES4 ) {
                slogger.info( entry.getKey() + " = " + BinStuffs.toHexString( mi.getBytesValue( mii ) ) );
            }
            else if( type == MIIGETTER.Type.INT ) {
                slogger.info( entry.getKey() + " = " + mi.getIntegerValue( mii ) );
            }
            else if( type == MIIGETTER.Type.RAWSTRING ) {
                slogger.info( entry.getKey() + " = " + mi.getStringValue( mii ) );
            }
            else {
                slogger.error( "***" + entry.getKey() + " : unkwon type = " + type );
            }
        }
    }

    public void testMiiGetterInspectionStructure()
    {// TODO
        slogger.info( "---------- testMiiGetterInspectionStructure() -----------");
        Map<String, MiiGetterIntrospectionItem> map = testMiiGetterInspection.getMap();

        for( Map.Entry<String, MiiGetterIntrospectionItem> entry : map.entrySet() ) {
            String                  beanName    = entry.getKey();
            MiiGetterIntrospectionItem item        = entry.getValue();

            assertNotNull( "Found a null beanName !",beanName);
            slogger.info( " - " + beanName + " - " + item );

            assertNotNull( "Not item found for " + beanName, item );

            Method methodGet = item.getGetterMethod();
            assertNotNull( "Not Getter found for " + beanName, methodGet );

            Method methodSet = item.getSetterMethod();
            assertNotNull( "Not Setter found for " + beanName, methodSet );

            MIIGETTER.Type type = item.getType();

            if( type == MIIGETTER.Type.INT ) {
                assertNotNull( "Min should be define for: " + beanName, item.getMinValue() );
                assertNotNull( "Max should be define for: " + beanName, item.getMaxValue() );
            }
        }
        slogger.info( "---------------------------------------------------------");
    }

    private int runCompareWithException( Mii m1, Mii mii2 )
    {
        int res;

        try {
            res = testMiiGetterInspection.compareWithException( mii, mii2 );

            assertTrue( "Should be alway true here", res == 0 );
        }
        catch( IntrospectionCompareException e ) {
            slogger.info( "Compare diff found using: " + e.getMethod() + " - " + e.getMessage() );

            res = e.getCompareValue();
        }
        catch( IntrospectionInvokeException e ) {
            slogger.warn( "Exception while compare: " + e.getMethod(), e );

            res = Integer.MIN_VALUE;
        }

        return res;
    }

}
